from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List, Optional, Dict, Any
import os
from openai import OpenAI
import json

app = FastAPI(
    title="会议纪要SMARTB解析服务",
    description="基于微调模型的会议纪要智能解析服务，按照SMARTB原则提取待办事项",
    version="1.0.0"
)

# 添加CORS中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 请求模型
class MeetingRecordRequest(BaseModel):
    content: str
    max_tokens: Optional[int] = 4096
    stream: Optional[bool] = False

# 响应模型
class TodoItem(BaseModel):
    S: str  # Specific
    M: str  # Measurable
    A: str  # Actionable
    R: str  # Relevant
    T: str  # Time-bound
    B: str  # Basis

class MeetingAnalysisResponse(BaseModel):
    todos: List[TodoItem]
    could_dos: List[TodoItem]
    raw_response: Optional[str] = None

# 初始化OpenAI客户端
try:
    import httpx
    client = OpenAI(
        api_key=os.getenv("SILICONFLOW_API_KEY", "sk-qstxvnwncinymkyuxnsyxvwujurekrazkepzvbzwzhqmkdtn"),
        base_url=os.getenv("SILICONFLOW_BASE_URL", "https://api.siliconflow.cn/v1"),
        http_client=httpx.Client(verify=False)
    )
    print("OpenAI客户端初始化成功")
except Exception as e:
    print(f"OpenAI客户端初始化失败: {e}")
    client = None

# 系统提示词
SYSTEM_PROMPT = """SMARTB原则解析:
S:specific,具体到行动上要完成这件事，我们需要先___，再___,最后__。
M:measurable,用___指标衡量这个行动是否达成了我们的目的。
A:actionable,对于我们现在的处境而言,我们可以利用已有的___去完成___。
R:relevent,这件事产生的原因及相关负责人___，这件事会影响的事件及相关负责人___,所以这件事的最终负责人是____。
T:time-bound,我们不能被任何一件事拖太久，所以我们定下截止日期是___。
B：basis，决策依据，洞见优于表象，记录支出决策的数据和逻辑是必要的，你的输出无疑是一堆待办项，但如果内容中的可办项或没必要办项被你列成了待办项，就会浪费不可估量的人力资源;因此，对于所有待办项，你都必须要输出其决策依据B内，供用户也供自己去判别这项行动是否值得被列入待办列表内

1.认识你的输入:
将{{ query }}的内容都是会议纪要。
2.认识你的处理方式:
从{{ query }}中抽离出待办列表，列表中的每一项都是一个符合SMART原则的行动计划;
3.认识你的输出: 
每一项行动计划作为一个object对象，S,M,A,R,T,B作为对象中的key,它们的内容作为对象中的value。
4.认识你输出的原则：
他们的决议非常重要，重点观察他们的遣词造句中有没有提到任务和负责人，有就是todo，没有就是coulddo，他们的已经决议出的行动计划你需要列入ToDo内,凡是进入ToDo内的事项，你都必须引用其决议原文放入B中，但会议并非完美无缺,他们没有决议但你觉得应该去做的行动，则列入couldDo内。"""

@app.get("/")
async def root():
    return {
        "message": "会议纪要SMARTB解析服务",
        "version": "1.0.0",
        "docs": "/docs"
    }

@app.post("/api/analyze-meeting", response_model=MeetingAnalysisResponse)
async def analyze_meeting(request: MeetingRecordRequest):
    if not client:
        raise HTTPException(status_code=500, detail="OpenAI客户端未正确初始化")
    
    try:
        messages = [
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": request.content}
        ]
        
        model_name = "ft:LoRA/Qwen/Qwen2.5-72B-Instruct:d1a2rj56d6ps73bus7hg:Qwen25-72BDecision-making:jlnkrdypkrboiikmgmce-ckpt_step_24"
        
        if request.stream:
            # 流式响应
            response = client.chat.completions.create(
                model=model_name,
                messages=messages,
                stream=True,
                max_tokens=request.max_tokens
            )
            
            result = ""
            for chunk in response:
                if chunk.choices[0].delta.content:
                    result += chunk.choices[0].delta.content
            
            # 这里简化处理，实际需要解析result中的JSON结构
            return MeetingAnalysisResponse(
                todos=[],
                could_dos=[],
                raw_response=result
            )
        else:
            # 非流式响应
            response = client.chat.completions.create(
                model=model_name,
                messages=messages,
                stream=False,
                max_tokens=request.max_tokens
            )
            
            result = response.choices[0].message.content
            
            # 这里简化处理，实际需要解析result中的JSON结构
            return MeetingAnalysisResponse(
                todos=[],
                could_dos=[],
                raw_response=result
            )
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"模型调用失败: {str(e)}")

@app.get("/api/health")
async def health_check():
    return {"status": "healthy", "service": "meeting-analysis"}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)